﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
using System.Globalization;
using ShredTheLog.Common.MVVM;
using ShredTheLog.Model;
using System.Collections.ObjectModel;
using ShredTheLog.Api.DataContracts;
using ShredTheLog.Api;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;

namespace ShredTheLog.ViewModels
{
    public sealed class UserProfileViewModel : ViewModelBase, IUserInfo
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        [Import]
        private ITranslatorSettingsSection TranslatorSettings { get; set; }

        [Import]
        private IConnectionSettingsSection ConnectionSettings { get; set; }

        [Import]
        public IRequestPrivateChatCommand RequestPrivateChatCommand { get; private set; }

        private IFullUserInfo _model;
        /// <summary>
        /// 
        /// </summary>
        /// <remarks>Используется в карточке пользователя в скине Odigo для подбора аватара (OdigoAvatarConverter).</remarks>
        public IFullUserInfo Model { get { return _model; } set { _model = value; OnPropertyChanged(() => Model); OnPropertyChanged(() => IsLoading); } }

        public bool IsLoading { get { return Model == null; } }

        public UserProfileViewModel(IUserInfo user)
        {
            Contract.Requires(user != null);

            Uid = user.Uid;
            var tui = user as IBasicUserInfo;
            if (tui != null)
            {
                Age = tui.Age;
                Country = tui.Country;
                Gender = tui.Gender;
                FirstName = tui.FirstName;
                LastName = tui.LastName;
                Name = tui.Name;

                var sui = user as IShortUserInfo;
                if (sui != null)
                {
                    KnownLanguages = new ReadOnlyObservableCollection<Language>(new ObservableCollection<Language>(sui.KnownLanguages));
                    PracticingLanguages = new ReadOnlyObservableCollection<Language>(new ObservableCollection<Language>(sui.PracticingLanguages));

                    var fui = user as IFullUserInfo;
                    if (fui != null)
                    {
                        Location = fui.Location;
                        RegistrationDate = fui.RegistrationDate;
                        ExchangesEmails = fui.ExchangesEmails;
                        ChatsOnline = fui.ChatsOnline;
                        Status = fui.US;
                        Description = fui.Description;
                        Model = fui;
                        return;
                    }
                }
            }

            ConnectionSettings.GetClient().GetFullUserInfo(user).ObserveOn(ShredServices.Dispatcher).Subscribe(
                result => 
                {
                    try
                    {
                        Age = result.Age;
                        Country = result.Country;
                        Gender = result.Gender;
                        FirstName = result.FirstName;
                        LastName = result.LastName;
                        Name = result.Name;
                        KnownLanguages = new ReadOnlyObservableCollection<Language>(new ObservableCollection<Language>(result.KnownLanguages));
                        PracticingLanguages = new ReadOnlyObservableCollection<Language>(new ObservableCollection<Language>(result.PracticingLanguages));
                        Location = result.Location;
                        RegistrationDate = result.RegistrationDate;
                        ExchangesEmails = result.ExchangesEmails;
                        ChatsOnline = result.ChatsOnline;
                        Status = result.US;
                        Description = result.Description;
                        Model = result;
                    }
                    catch (Exception ex)
                    {
                        ShredServices.ShowError(ex);
                    }
                }, 
                ShredServices.ShowError);
        }

        public int Uid { get; private set; }

        private int? _age;
        public int? Age { get { return _age; } private set { _age = value; OnPropertyChanged(() => Age); } }
        private Country? _country;
        public Country? Country { get { return _country; } private set { _country = value; OnPropertyChanged(() => Country); } }
        private Gender _gender;
        public Gender Gender { get { return _gender; } private set { _gender = value; OnPropertyChanged(() => Gender); } }
        private string _firstName;
        public string FirstName { get { return _firstName; } private set { _firstName = value; OnPropertyChanged(() => FirstName); } }
        private string _lastName;
        public string LastName { get { return _lastName; } private set { _lastName = value; OnPropertyChanged(() => LastName); } }
        private string _name;
        public string Name { get { return _name; } private set { _name = value; OnPropertyChanged(() => Name); } }

        private ReadOnlyObservableCollection<Language> _knownLanguages;
        public ReadOnlyObservableCollection<Language> KnownLanguages { get { return _knownLanguages; } private set { _knownLanguages = value; OnPropertyChanged(() => KnownLanguages); } }
        private ReadOnlyObservableCollection<Language> _practicingLanguage;
        public ReadOnlyObservableCollection<Language> PracticingLanguages { get { return _practicingLanguage; } private set { _practicingLanguage = value; OnPropertyChanged(() => PracticingLanguages); } }

        private string _location;
        public string Location { get { return _location; } private set { _location = value; OnPropertyChanged(() => Location); } }
        private DateTime? _registrationDate;
        public DateTime? RegistrationDate { get { return _registrationDate; } private set { _registrationDate = value; OnPropertyChanged(() => RegistrationDate); } }
        private bool? _exchangesEmails;
        public bool? ExchangesEmails { get { return _exchangesEmails; } private set { _exchangesEmails = value; OnPropertyChanged(() => ExchangesEmails); } }
        private bool? _chatsOnline;
        public bool? ChatsOnline { get { return _chatsOnline; } private set { _chatsOnline = value; OnPropertyChanged(() => ChatsOnline); } }
        private string _status;
        public string Status { get { return _status; } private set { _status = value; OnPropertyChanged(() => Status); } }

        private string _description;
        public string Description 
        { 
            get { return _description; } 
            private set 
            { 
                _description = value;
                OnPropertyChanged(() => Description);
            } 
        }

        public bool IsWindowClosed
        {
            get { return _isWindowClosed; }
            set { _isWindowClosed = value; OnPropertyChanged(() => IsWindowClosed); }
        }
        private bool _isWindowClosed;

        private ICommand _closeCommand;
        public ICommand CloseCommand
        {
            get
            {
                if (_closeCommand == null)
                {
                    _closeCommand = new DelegateCommand(() => { IsWindowClosed = true; });
                }
                return _closeCommand;
            }
        }
    }

    [ValueConversion(typeof(IUserInfo), typeof(UserProfileConverter))]
    public sealed class UserProfileConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var user = (IUserInfo)value;
            // Тут может быть ситуация, когда user == null (если список, к текущему значению которого осуществлялась привязка, пуст)
            return user != null ? new UserProfileViewModel(user) : null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        public static readonly UserProfileConverter Default = new UserProfileConverter();
    }
}
